package com.mjk.common.web.getway.conf.selector;

import com.alibaba.spring.util.BeanRegistrar;

import com.mjk.common.core.drpc.DrpcAnnotationBeanFactory;
import com.mjk.common.web.getway.annotation.EnableGetWay;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;

import org.apache.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationPostProcessor;
import org.apache.dubbo.config.spring.context.DubboSpringInitializer;
import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;

import java.util.*;

import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;

public class BeeDubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar{
	public BeeDubboComponentScanRegistrar() {
	}

	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		DubboSpringInitializer.initialize(registry);
		Set<String> packagesToScan = this.getPackagesToScan(importingClassMetadata);
		this.registerServiceAnnotationPostProcessor(packagesToScan, registry);
	}

	private void registerServiceAnnotationPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ServiceAnnotationPostProcessor.class);
		builder.addConstructorArgValue(packagesToScan);
		builder.setRole(2);
		AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
		BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
		//注册dubbo 配置信息
		BeanDefinitionBuilder builder1 = BeanDefinitionBuilder.rootBeanDefinition(DrpcAnnotationBeanFactory.class);
		AbstractBeanDefinition beanDefinition1 = builder1.getBeanDefinition();
		BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition1, registry);
	}

	private Set<String> getPackagesToScan(AnnotationMetadata metadata) {
		Set<String> packagesToScan = this.getPackagesToScan0(metadata, DubboComponentScan.class, "basePackages", "basePackageClasses");
		if (packagesToScan.isEmpty()) {
			packagesToScan = this.getPackagesToScan0(metadata, EnableDubbo.class, "scanBasePackages", "scanBasePackageClasses");
		}

		return packagesToScan.isEmpty() ? Collections.singleton(ClassUtils.getPackageName(metadata.getClassName())) : packagesToScan;
	}

	private Set<String> getPackagesToScan0(AnnotationMetadata metadata, Class annotationClass, String basePackagesName, String basePackageClassesName) {
		AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClass.getName()));
		if (attributes == null) {
			return Collections.emptySet();
		} else {
			Set<String> packagesToScan = new LinkedHashSet();
			String[] basePackages = attributes.getStringArray(basePackagesName);
			packagesToScan.addAll(Arrays.asList(basePackages));
			Class<?>[] basePackageClasses = attributes.getClassArray(basePackageClassesName);
			Class[] var9 = basePackageClasses;
			int var10 = basePackageClasses.length;

			for (int var11 = 0; var11 < var10; ++var11) {
				Class<?> basePackageClass = var9[var11];
				packagesToScan.add(ClassUtils.getPackageName(basePackageClass));
			}

			if (attributes.containsKey("value")) {
				String[] value = attributes.getStringArray("value");
				packagesToScan.addAll(Arrays.asList(value));
			}

			return packagesToScan;
		}
	}
}
